// $Id: input_idl.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/foreach.hpp>
#include <xpgen/input_idl.hpp>
#include <xpgen/input_xpt.hpp>
#include "names.hpp"

using namespace std;
namespace fs = boost::filesystem;

namespace xpgen {

input_idl::input_idl() :
    guess_notxpcom_result(false)
{
}

input_idl::~input_idl()
{
}

void input_idl::do_reset()
{
    input::do_reset();
}

void input_idl::do_module()
{
    // Check input file
    size_t in_size = static_cast<size_t>(fs::file_size(input_file));
    if (in_size == 0) {
        throw runtime_error(
                "file (" + input_file.file_string() + ") is empty");
    }

    // Compile the idl into xpt
    if (verbose)
        cout << ">>> Processing IDL file (" << input_file.leaf() << ")..." << endl;

    // Output xpt path
    char tmpp[1024];
    tmpnam(tmpp);
    strcat(tmpp, ".xpt");
    fs::path xpt_path(tmpp);
    xpt_path.normalize();

    fs::path xpt_dir = xpt_path.branch_path();

    // Command
    string cmd;
    if (xpidl_path.empty() || !fs::exists(xpidl_path)) {
        cmd = N_xpidl;
    } else {
        cmd = "\"";
        cmd += xpidl_path.file_string();
        cmd += "\"";
    }

    cmd += " -m typelib -w";
    if (verbose)
        cmd += " -v";

    BOOST_FOREACH(const fs::path& p, include_paths)
    {
        cmd += " -I \"";
        cmd += p.directory_string();
        cmd += "\"";
    }

    cmd += " -e \"";
    cmd += xpt_path.file_string();
    cmd += "\"";

    cmd += " \"";
    cmd += input_file.file_string();
    cmd += "\"";

    // Execute
    if (verbose)
        cout << "=== Executing command (" << cmd << ").." << endl;

    int ret = system(cmd.c_str());
    if (ret) {
        fs::remove(xpt_path);
        throw new runtime_error("failed to execute (" + cmd + ")");
    }

    // XPT process
    try {
        input_xpt in;

        in.verbose = verbose;
        in.input_dir = xpt_dir;
        in.input_file = xpt_path;
        in.ns_override = ns_override;

        in.guess_notxpcom_result = guess_notxpcom_result;

        in.do_all(module());
        fs::remove(xpt_path);

    } catch (...) {
        fs::remove(xpt_path);
        throw;
    }

    if (verbose)
        cout << ">>> End processing IDL file (" << input_file.leaf() << ")." << endl;
}

} // namespace xpgen
